﻿Imports Commander_Wars.Grafikengine
Imports Microsoft.DirectX.Direct3D
Imports Microsoft.DirectX
Public Module Spieletools
    ''' <summary>
    ''' Loads a RIFF.PAl FIle
    ''' </summary>
    ''' <param name="File"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetPalette(ByVal File As String) As Bitmap
        Dim Palette As Bitmap
        Using StrR As New IO.FileStream(File, IO.FileMode.Open)

            'RIFF
            For I = 0 To 3
                Select Case I
                    Case 0
                        If "R" <> ByteToChar(StrR.ReadByte()) Then
                            Return New Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
                        End If
                    Case 1
                        If "I" <> ByteToChar(StrR.ReadByte()) Then
                            Return New Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
                        End If
                    Case 2
                        If "F" <> ByteToChar(StrR.ReadByte()) Then
                            Return New Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
                        End If
                    Case 3
                        If "F" <> ByteToChar(StrR.ReadByte()) Then
                            Return New Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
                        End If
                End Select

            Next
            'Size?
            For I = 0 To 3
                StrR.ReadByte()
            Next
            '"Pal "
            For I = 0 To 3
                StrR.ReadByte()
            Next
            'Data
            For I = 0 To 3
                StrR.ReadByte()
            Next
            'Size?
            For I = 0 To 3
                StrR.ReadByte()
            Next
            'Size?
            For I = 0 To 1
                StrR.ReadByte()
            Next
            Dim By(1) As Byte
            For I = 0 To 1
                By(1 - I) = StrR.ReadByte()
            Next
            Dim Height As Integer = BitConverter.ToInt16(By, 0)
            Palette = New Bitmap(((StrR.Length - 6 * 4) / 4) / Height, Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
            Dim I2 As Integer = 0
            Height = 0
            While StrR.Position < StrR.Length
                Dim r As Byte = StrR.ReadByte
                Dim g As Byte = StrR.ReadByte
                Dim b As Byte = StrR.ReadByte
                StrR.ReadByte() 'End of Color Bit
                Palette.SetPixel(I2, Height, Color.FromArgb(255, r, g, b))
                I2 += 1
                If I2 >= Palette.Width Then
                    I2 = 0
                    Height += 1
                End If
            End While
        End Using
        Return Palette
    End Function
#Region "Allgemeins"
    Public Const Meereshoehe As Single = -0.1
    Public Enum KampfanimationsTypen
        Alle
        Eigene
        Feindliche
        Keine
    End Enum
    Public Function ReplcaceGermanLetters(ByVal Z As String) As String
        Z = Z.Replace("ö", "oe")
        Z = Z.Replace("Ö", "Oe")
        Z = Z.Replace("Ä", "Ae")
        Z = Z.Replace("ä", "ae")
        Z = Z.Replace("Ü", "Ue")
        Z = Z.Replace("ü", "ue")
        Z = Z.Replace("ß", "ss")
        Return Z
    End Function

    Public Enum KompassRichtungen
        N = 1
        O = 2
        S = 4
        W = 8
    End Enum

    ''' <summary>
    ''' Normal time a Thread should sleep while waiting for the next Action.
    ''' </summary>
    ''' <remarks></remarks>
    Public Const ThreadSleepTime As Integer = 10

    Public Function Schreiben(ByVal Zeichenkette As String, ByVal Index As Integer, ByVal Neutxt As String) As String
        Zeichenkette = Schreiben(Zeichenkette, Index, Neutxt, "_")
        Return Zeichenkette
    End Function

    Public Function Schreiben(ByVal Zeichenkette As String, ByVal Index As Integer, ByVal Neutxt As String, ByVal Trennzeichen As String) As String
        If Zeichenkette = "" Then
            Return ""
        Else
            Dim sAntwort As String()
            Dim sTrennzeichen As Char()

            sTrennzeichen = Trennzeichen
            sAntwort = Zeichenkette.Split(sTrennzeichen)
            If sAntwort.Length > Index Then
                'sAntwort(Index) = Neutxt

                Dim Max As Integer
                Max = sAntwort.Length
                If Index <= Max Then
                    If 0 < Max Then
                        Zeichenkette = uSchreiben(sAntwort(0), 0, Index, Neutxt)
                    End If
                    Dim oft As Integer
                    Dim I As Integer = 1
                    For oft = 1 To (Max - 1)
                        If I < Max Then
                            Zeichenkette += sTrennzeichen + uSchreiben(sAntwort(I), I, Index, Neutxt)
                        End If
                        I = I + 1
                    Next
                    Return Zeichenkette
                Else
                    Return Nothing
                End If
            Else
                Dim Ueberschuss As Integer
                Ueberschuss = Index - sAntwort.Length
                Dim I As Integer
                For I = 0 To Ueberschuss
                    Zeichenkette += Trennzeichen
                Next
                Return Schreiben(Zeichenkette, Index, Neutxt, Trennzeichen)
            End If
        End If
    End Function
    Private Function uSchreiben(ByVal Textteil As String, ByVal Indextxt As Integer, ByVal Index As Integer, ByVal Neutxt As String)
        Select Case Indextxt
            Case Is < Index
                Return Textteil
            Case Is > Index
                Return Textteil
            Case Is = Index
                Return Neutxt
            Case Else
                Return ""
        End Select
    End Function




    Public Function getBtnZeile(ByVal ButtonTag As String) As String
        Return Splitten(ButtonTag, 2)
    End Function
    Public Function getBtnZeileNum(ByVal ButtonTag As String) As Integer
        Dim Zeile As New Integer

        Zeile = getBtnZeile(ButtonTag)
        Return Zeile
    End Function


    Public Function getBtnSpalte(ByVal ButtonTag As String) As String
        Return Splitten(ButtonTag, 3)
    End Function
    Public Function getBtnSpalteNum(ByVal ButtonTag As String) As Integer
        Dim Zeile As New Integer

        Zeile = getBtnZeile(ButtonTag)
        Return Zeile
    End Function



    Public Function Splitten(ByVal Zeichenkette As String, ByVal Index As Integer) As String
        Return Splitten(Zeichenkette, Index, "_")
    End Function
    Public Function Splitten(ByVal Zeichenkette As String, ByVal Index As Integer, ByVal Trennzeichen As String) As String
        Dim sAntwort As String()
        Dim sTrennzeichen As Char()
        If Zeichenkette = "" Then
            Return ""
        Else
            sTrennzeichen = Trennzeichen
            sAntwort = Zeichenkette.Split(sTrennzeichen)
            If sAntwort.Length > Index Then
                'If sAntwort.Length >= Index Then
                Return sAntwort(Index)
                'Else
                'Return Nothing
                'End If
            Else
                Return "Zu Hoher Index"
            End If
        End If
    End Function

    Public Zufall As Random
    Public Function Zufallszahl(ByVal min As Integer, ByVal max As Integer) As Integer

        If Zufall Is Nothing Then
            Randomize()
            Zufall = New Random
        End If
        Dim X2 As Integer = 0
        If min < 0 Then
            X2 = min
            max = max - min
            min = 0
        End If

        Dim Zahl As Integer '3-5
        Zahl = Math.Round((Zufall.NextDouble * (max - min + 1)), System.MidpointRounding.ToEven) + min
        If Zahl > max Then Zahl = max
        If Zahl < min Then Zahl = min
        Zahl = Zahl + X2
        Return Zahl
    End Function

    ''' <summary>
    ''' Stellt einen eindimensionalen Array zweidimensional dar
    ''' </summary>
    ''' <param name="X">X Position im Array beginnt mit 0</param>
    ''' <param name="Y">Y Position im Array beginnt mit 0</param>
    ''' <param name="Breite">Die Konstantebreite des Array beginnend mit 1</param>
    ''' <returns>Gibt die Stelle im eindimensionalen Array zurueck</returns>
    ''' <remarks></remarks>
    Public Function Arraystelle(ByVal X As Integer, ByVal Y As Integer, ByVal Breite As Integer)
        Dim Stelle As Integer = (Y * Breite) + X
        Return Stelle
    End Function

    ''' <summary>
    ''' Gibt alle Vorkommenden Teile des Arrays zurueck
    ''' </summary>
    ''' <param name="Element">Der Zu durchsuchende Array</param>
    ''' <param name="Parameter">Der gesuchte Parameter</param>
    ''' <param name="GenauGleich">Muss der String identisch oder nur aehnlich sein</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function FindallElements(ByVal Element() As String, ByVal Parameter As String, Optional ByVal GenauGleich As Boolean = False) As Integer()
        Dim I() As Integer = {}
        Dim I0 As Integer = 0
        For Each Name In Element
            If GenauGleich = False Then
                If Name.Contains(Parameter) = True Then
                    Array.Resize(I, I.Length + 1)
                    I(I.Length - 1) = I0
                End If
            Else
                If Name = Parameter Then
                    Array.Resize(I, I.Length + 1)
                    I(I.Length - 1) = I0
                End If
            End If
            I0 += 1
        Next
        Return I
    End Function
    ''' <summary>
    ''' Gibt das erste Vorkommende Teil des Arrays zurueck
    ''' </summary>
    ''' <param name="Arra">Der Zu durchsuchende Array</param>
    ''' <param name="Parameter">Der gesuchte Parameter</param>
    ''' <param name="GenauGleich">Muss der String identisch oder nur aehnlich sein</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function FindElement(ByVal Arra() As String, ByVal Parameter As String, Optional ByVal GenauGleich As Boolean = False) As Integer
        For I = 0 To Arra.Length - 1
            If GenauGleich = False Then
                If Arra(I).Contains(Parameter) = True Then
                    Return I
                End If
            Else
                If Arra(I) = Parameter Then
                    Return I
                End If
            End If
        Next
        Return -1
    End Function
    Public Function IstGerade(ByVal Zahl As Integer) As Boolean
        Dim Rest As Integer
        Math.DivRem(Zahl, 2, Rest)
        If Rest = 1 Then
            Return False
        Else
            Return True
        End If
    End Function
    ''' <summary>
    ''' Erstellt ein Parallelogramm(Kreis in Feldern
    ''' </summary>
    ''' <param name="Radius">Der maximale Abstand eines Feldes (0=1 Feld grosse Rueckgabe)</param>
    ''' <returns>Gibt einen Array zurueck in dem -1 fuer nicht Ereichbar steht und der 2*Radius+1 gross ist in Hoehe und Breite</returns>
    ''' <remarks></remarks>
    Public Function Kreisfunktion(ByVal Radius As Integer) As Integer(,)
        Dim Quadrat(,) As Integer = {}
        If Radius >= 0 Then
            ReDim Quadrat(Radius * 2, Radius * 2)
        Else
            ReDim Quadrat(-1, -1)
        End If
        For X = 0 To Radius * 2
            For Y = 0 To Radius * 2
                Quadrat(X, Y) = -1
            Next
        Next
        If Quadrat.Length > 0 Then
            Quadrat(Radius, Radius) = 0
        End If
        For MomentanterRadius = 1 To Radius
            Dim StartX As Integer = Radius
            Dim StartY As Integer = Radius - MomentanterRadius
            For I = 1 To MomentanterRadius
                StartX += 1
                StartY += 1
                Quadrat(StartX, StartY) = MomentanterRadius
            Next
            For I = 1 To MomentanterRadius
                StartX -= 1
                StartY += 1
                Quadrat(StartX, StartY) = MomentanterRadius
            Next
            For I = 1 To MomentanterRadius
                StartX -= 1
                StartY -= 1
                Quadrat(StartX, StartY) = MomentanterRadius
            Next
            For I = 1 To MomentanterRadius
                StartX += 1
                StartY -= 1
                Quadrat(StartX, StartY) = MomentanterRadius
            Next
        Next
        Return Quadrat
    End Function
    ''' <summary>
    ''' Gibt die aeussersten Felder eines Kreises zurueck 
    ''' </summary>
    ''' <param name="Radius">Der Radius des Kreises</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Kreisfelder(ByVal Radius As Integer) As Point()
        Dim Felder() As Point = {}
        If Radius = 0 Then
            Felder = New Point() {New Point}
        Else

            Dim StartX As Integer = -Radius
            Dim StartY As Integer = 0
            For I = 1 To Radius
                StartX += 1
                StartY -= 1
                Array.Resize(Felder, Felder.Length + 1)
                Felder(Felder.Length - 1) = New Point(StartX, StartY)
            Next
            For I = 1 To Radius
                StartX += 1
                StartY += 1
                Array.Resize(Felder, Felder.Length + 1)
                Felder(Felder.Length - 1) = New Point(StartX, StartY)
            Next
            For I = 1 To Radius
                StartX -= 1
                StartY += 1
                Array.Resize(Felder, Felder.Length + 1)
                Felder(Felder.Length - 1) = New Point(StartX, StartY)
            Next
            For I = 1 To Radius
                StartX -= 1
                StartY -= 1
                Array.Resize(Felder, Felder.Length + 1)
                Felder(Felder.Length - 1) = New Point(StartX, StartY)
            Next
        End If
        Return Felder
    End Function
    Public Function Rechteck(ByVal Laenge As Integer) As Point()
        Dim Felder(Laenge, Laenge) As Integer
        Dim Punkte(Felder.Length - 1) As Point
        Dim I As Integer = 0
        Dim S As Integer = Math.DivRem(Laenge, 2, 0)
        For X = -S To S
            For Y = -S To S
                Punkte(I) = New Point(X, Y)
                I += 1
            Next
        Next
        Return Punkte
    End Function
    ''' <summary>
    ''' Konvertiert einen String in eine Zahl
    ''' </summary>
    ''' <param name="Zahl"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CZahl(ByVal Zahl As String) As Integer
        Return CInt(Zahl)
    End Function
    ''' <summary>
    ''' Gibt die KP von 0-10 zurueck berechnet aus 0-100.
    ''' </summary>
    ''' <param name="Leben"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function getKP(ByVal Leben As Single) As Integer
        If Leben > 100 Then Leben = 100
        If Leben < 0 Then Leben = 0
        Dim I As Integer = Math.DivRem(CInt(Leben), 10, 0)
        If I < 0 Then
            Return 0
        End If
        If Leben - I * 10 > 0 Then
            I += 1
        End If
        Return I
    End Function
    ''' <summary>
    ''' Teilt zwei Zahlen und gibt immer aufgerundete Werte zurueck
    ''' </summary>
    ''' <param name="Nenner"></param>
    ''' <param name="Zaehler"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Divi(ByVal Nenner As Integer, ByVal Zaehler As Integer) As Integer
        Dim R As Integer
        Dim Z As Integer = Math.DivRem(Nenner, Zaehler, R)
        If R > 0 Then Z += 1
        Return Z
    End Function
    ''' <summary>
    ''' Gibt fuer NUDS die Vergroesserung ihres Wertes zurueck
    ''' </summary>
    ''' <param name="Wert"></param>
    ''' <param name="Naehrungsschritte"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Round(ByVal Wert As Integer, ByVal Naehrungsschritte As Integer) As Integer
        Dim R As Integer
        Dim Rueckgabe As Integer = Math.DivRem(Wert, Naehrungsschritte, R)
        Rueckgabe *= Naehrungsschritte
        If Naehrungsschritte / 2 < R Then
            Rueckgabe += Naehrungsschritte
        End If
        Return Rueckgabe
    End Function

    Public Function CPoint(ByVal P As String) As Point
        Dim P2() As String = P.Split(",")
        Dim P1 As String = P2(1).Remove(0, 2)

        Return New Point(P2(0).Remove(0, 3), P1.Remove(P1.Length - 1))
    End Function

    Public Function ToIntArry(ByVal Arra As String()) As Integer()
        If Arra(0) <> "" Or Arra.Length > 1 Then
            Dim Int(Arra.Length - 1) As Integer
            For I = 0 To Arra.Length - 1
                If Arra(I) = "" Then
                    Int(I) = 0
                Else
                    Int(I) = Arra(I)
                End If
            Next
            Return Int
        Else
            Return New Integer() {}
        End If

    End Function
    Public Function ToDecArry(ByVal Arra As String()) As Decimal()
        If Arra(0) <> "" Or Arra.Length > 1 Then
            Dim Int(Arra.Length - 1) As Decimal
            For I = 0 To Arra.Length - 1
                If Arra(I) = "" Then
                    Int(I) = 0
                Else
                    Int(I) = Arra(I)
                End If
            Next
            Return Int
        Else
            Return New Decimal() {}
        End If
    End Function


    Public Function FarbtabelleToString(ByVal B As Bitmap) As String
        Dim S As String = ""
        For I = 0 To B.Width - 1
            If I = B.Width - 1 Then
                S += B.GetPixel(I, 0).ToArgb.ToString
            Else
                S += B.GetPixel(I, 0).ToArgb.ToString + "_"
            End If
        Next
        Return S
    End Function
    Public Function StringToFarbtabelle(ByVal S() As String) As Image
        Dim B As New Bitmap(S.Length, 1, Drawing.Imaging.PixelFormat.Format24bppRgb)
        For I = 0 To S.Length - 1
            B.SetPixel(I, 0, Color.FromArgb(CInt(S(I))))
        Next
        Return B
    End Function

    Public Function Distance(ByVal P1 As Point, ByVal P2 As Point) As Integer
        Return Math.Abs(P1.X - P2.X) + Math.Abs(P1.Y - P2.Y)
    End Function
    Public Function Distance(ByVal X1 As Integer, ByVal Y1 As Integer, ByVal X2 As Integer, ByVal Y2 As Integer) As Integer
        Return Math.Abs(X1 - X2) + Math.Abs(Y1 - Y2)
    End Function

    Public Function IntArrayToStr(ByVal IntArra As Integer()) As String
        Dim S As String = ""
        For I = 0 To IntArra.Length - 1
            If IntArra.Length - 1 = I Then
                S += IntArra(I).ToString
            Else
                S += IntArra(I).ToString + "_"
            End If
        Next
        Return S
    End Function
    Public Function ToSTR(ByVal Arra() As Object) As String
        Dim S As String = ""
        If Arra IsNot Nothing Then
            If Arra.Length > 0 Then
                If Arra(0) <> "" Or Arra.Length > 1 Then
                    For I = 0 To Arra.Length - 1
                        If I = Arra.Length - 1 Then
                            S += Arra(I).ToString
                        Else
                            S += Arra(I).ToString + "|"
                        End If
                    Next
                End If
            End If
        End If
        Return S
    End Function
    Public Function ToSTR(ByVal Arra() As ObjektSpielfeld.Wetterarten) As String
        Dim S As String = ""
        If Arra IsNot Nothing Then
            If Arra.Length > 0 Then
                For I = 0 To Arra.Length - 1
                    If I = Arra.Length - 1 Then
                        S += CInt(Arra(I)).ToString
                    Else
                        S += CInt(Arra(I)).ToString + "|"
                    End If
                Next
            End If
        End If
        Return S
    End Function

    Public Function GetDistance(ByVal X1 As Integer, ByVal Y1 As Integer, ByVal X2 As Integer, ByVal Y2 As Integer) As Integer
        Return Math.Abs(X1 - X2) + Math.Abs(Y1 - Y2)
    End Function
    Public Function GetDistance(ByVal P1 As Point, ByVal P2 As Point) As Integer
        Return GetDistance(P1.X, P1.Y, P2.X, P2.Y)
    End Function

    Public Function GetScreenResolutions(ByRef MomPos As Integer) As List(Of String)
        Dim Liste As New List(Of String)
        Try
            Dim dispmode As DisplayMode
            Dim adapterinfo As AdapterInformation = Manager.Adapters(DataSettings.Adapter)

            For Each dispmode In adapterinfo.SupportedDisplayModes

                If dispmode.Format = Format.R5G6B5 And dispmode.RefreshRate = 60 Then
                    Liste.Add(dispmode.Width & " x " & _
                                             dispmode.Height & " x " & _
                                             16)
                ElseIf dispmode.Format = Format.X8R8G8B8 And dispmode.RefreshRate = 60 Then
                    Liste.Add(dispmode.Width & " x " & _
                                            dispmode.Height & " x " & _
                                            32)
                End If
                If dispmode.Equals(adapterinfo.CurrentDisplayMode) Then
                    MomPos = Liste.Count - 1
                End If
            Next
        Catch err As Direct3DXException
            Konsole.Write("DirectX Exception during Screen-Resolution check. " + err.ToString)
        Catch
            Konsole.Write("Unkown Error during Screen-Resolution check.")
        End Try
        Return Liste
    End Function

    Public Function IsBoolean(ByVal Obj As Object) As Boolean
        If Obj.ToString.ToLower = "true" Or Obj.ToString.ToLower = "false" Or IsNumeric(Obj) Then
            Return True
        Else
            Return False
        End If
    End Function

    Public Function GetArmyOutFit(ByVal Army As String) As String
        Select Case Army
            Case "BG"
                Return "BH"
            Case Else
                Return Army
        End Select
    End Function

    Public Function LoadRule(ByVal Gamemode As CommanderWarsGameModi, ByVal Spielerzahl As Integer) As ObjektRegeln
        Dim Regel As New ObjektRegeln(Spielerzahl, True)
        Select Case Gamemode
            Case CommanderWarsGameModi.AdvanceWarsDC
                'Baublockade
                Regel.BauBlockade = False
                'Teurungsrate
                Regel.Teurungsrate = 0
                'Rang Modus
                Regel.LevelModus = True
                'Luftschlacht
                Regel.Luftschlacht = False
                'Doppelgabe
                Regel.DoppelGabe = False
                'KO System
                Regel.KOSystem = KOSysteme.KO_Modus
                'Gebaeudezerstoerung
                Regel.GebaeudeZerstoerung = False
                'Glueck
                Regel.NoLuck = False
                'Gebaeude Schwachstelle
                Regel.KeineGebaeudeSchwachstelle = False
                'Gaben
                Regel.KeineGaben = False
                'Einheitenlimit
                Regel.MaxTroops = 50
                'Weather
                'Sun
                Regel.Wetterwahrscheinlichkeiten(0) = 70
                'Rain
                Regel.Wetterwahrscheinlichkeiten(1) = 10
                'Snow
                Regel.Wetterwahrscheinlichkeiten(2) = 10
                'Sanstorm
                Regel.Wetterwahrscheinlichkeiten(3) = 10
            Case CommanderWarsGameModi.AdvanceWars
                'Baublockade
                Regel.BauBlockade = False
                'Teurungsrate
                Regel.Teurungsrate = 0
                'Rang Modus
                Regel.LevelModus = False
                'Luftschlacht
                Regel.Luftschlacht = False
                'Doppelgabe
                Regel.DoppelGabe = False
                'KO System
                Regel.KOSystem = KOSysteme.Gabe_Modus
                'Gebaeudezerstoerung
                Regel.GebaeudeZerstoerung = False
                'Glueck
                Regel.NoLuck = False
                'Gebaeude Schwachstelle
                Regel.KeineGebaeudeSchwachstelle = False
                'Gaben
                Regel.KeineGaben = False
                'Einheitenlimit
                Regel.MaxTroops = 50
                'Weather
                'Sun
                Regel.Wetterwahrscheinlichkeiten(0) = 80
                'Rain
                Regel.Wetterwahrscheinlichkeiten(1) = 10
                'Snow
                Regel.Wetterwahrscheinlichkeiten(2) = 10
                'Sanstorm
                Regel.Wetterwahrscheinlichkeiten(3) = 0
            Case CommanderWarsGameModi.AdvanceWars2
                'Baublockade
                Regel.BauBlockade = False
                'Teurungsrate
                Regel.Teurungsrate = 0
                'Rang Modus
                Regel.LevelModus = False
                'Luftschlacht
                Regel.Luftschlacht = False
                'Doppelgabe
                Regel.DoppelGabe = False
                'KO System
                Regel.KOSystem = KOSysteme.Gabe_Modus
                'Gebaeudezerstoerung
                Regel.GebaeudeZerstoerung = False
                'Glueck
                Regel.NoLuck = False
                'Gebaeude Schwachstelle
                Regel.KeineGebaeudeSchwachstelle = False
                'Gaben
                Regel.KeineGaben = False
                'Einheitenlimit
                Regel.MaxTroops = 50
                'Weather
                'Sun
                Regel.Wetterwahrscheinlichkeiten(0) = 80
                'Rain
                Regel.Wetterwahrscheinlichkeiten(1) = 10
                'Snow
                Regel.Wetterwahrscheinlichkeiten(2) = 10
                'Sanstorm
                Regel.Wetterwahrscheinlichkeiten(3) = 0
            Case CommanderWarsGameModi.AdvanceWarsDS
                'Baublockade
                Regel.BauBlockade = False
                'Teurungsrate
                Regel.Teurungsrate = 0
                'Rang Modus
                Regel.LevelModus = False
                'Luftschlacht
                Regel.Luftschlacht = False
                'Doppelgabe
                Regel.DoppelGabe = True
                'KO System
                Regel.KOSystem = KOSysteme.Gabe_Modus
                'Gebaeudezerstoerung
                Regel.GebaeudeZerstoerung = False
                'Glueck
                Regel.NoLuck = False
                'Gebaeude Schwachstelle
                Regel.KeineGebaeudeSchwachstelle = False
                'Gaben
                Regel.KeineGaben = False
                'Einheitenlimit
                Regel.MaxTroops = 50
                'Weather
                'Sun
                Regel.Wetterwahrscheinlichkeiten(0) = 70
                'Rain
                Regel.Wetterwahrscheinlichkeiten(1) = 10
                'Snow
                Regel.Wetterwahrscheinlichkeiten(2) = 10
                'Sanstorm
                Regel.Wetterwahrscheinlichkeiten(3) = 10
            Case CommanderWarsGameModi.CommanderWars
                'Baublockade
                Regel.BauBlockade = False
                'Teurungsrate
                Regel.Teurungsrate = 0
                'Rang Modus
                Regel.LevelModus = True
                'Luftschlacht
                Regel.Luftschlacht = True
                'Doppelgabe
                Regel.DoppelGabe = True
                'KO System
                Regel.KOSystem = KOSysteme.Gabe_Modus
                'Gebaeudezerstoerung
                Regel.GebaeudeZerstoerung = True
                'Glueck
                Regel.NoLuck = False
                'Gebaeude Schwachstelle
                Regel.KeineGebaeudeSchwachstelle = True
                'Gaben
                Regel.KeineGaben = False
                'Einheitenlimit
                Regel.MaxTroops = -1
                'Weather
                'Sun
                Regel.Wetterwahrscheinlichkeiten(0) = 70
                'Rain
                Regel.Wetterwahrscheinlichkeiten(1) = 10
                'Snow
                Regel.Wetterwahrscheinlichkeiten(2) = 10
                'Sanstorm
                Regel.Wetterwahrscheinlichkeiten(3) = 10
            Case CommanderWarsGameModi.CommanderWars2
                'Baublockade
                Regel.BauBlockade = True
                'Teurungsrate
                Regel.Teurungsrate = 100
                'Rang Modus
                Regel.LevelModus = True
                'Luftschlacht
                Regel.Luftschlacht = False
                'Doppelgabe
                Regel.DoppelGabe = False
                'KO System
                Regel.KOSystem = KOSysteme.CoW_Hybrid
                'Gebaeudezerstoerung
                Regel.GebaeudeZerstoerung = True
                'Glueck
                Regel.NoLuck = False
                'Gebaeude Schwachstelle
                Regel.KeineGebaeudeSchwachstelle = True
                'Gaben
                Regel.KeineGaben = False
                'Einheitenlimit
                Regel.MaxTroops = -1
                'Weather
                'Sun
                Regel.Wetterwahrscheinlichkeiten(0) = 70
                'Rain
                Regel.Wetterwahrscheinlichkeiten(1) = 10
                'Snow
                Regel.Wetterwahrscheinlichkeiten(2) = 10
                'Sanstorm
                Regel.Wetterwahrscheinlichkeiten(3) = 10
        End Select
        Return Regel
    End Function
#End Region
#Region "Speichern und Laden"
#Region "Version Konstants"
    Const SpielerVersion As Byte = 0
    Const GameHeaderVersion As Byte = 0
#End Region

    Public Sub SaveMap(ByVal Name As String, Optional ByVal Endung As String = ".map", Optional ByVal Spielfeld As ObjektSpielfeld = Nothing, Optional ByVal KompletterPfad As Boolean = False)
        If Spielfeld Is Nothing Then
            Spielfeld = Objektverwalter.Spielfeld
        End If
        Dim Pfad As String = Name
        If Name.ToLower.EndsWith(".sav") Or Name.ToLower.EndsWith(".txt") Or Name.ToLower.EndsWith(".map") Then
            Name = Name.Remove(Name.Length - 4)
        End If
        If Name.Contains("\") Then
            Name = Name.Remove(0, Name.LastIndexOf("\") + 1)
        End If
        If Name.ToLower.EndsWith(".map") Then
            If Spielfeld.Kartenname = "" Or Spielfeld.Kartenname = "Karte" Then
                Spielfeld.Kartenname = Name
            End If
        End If
        If KompletterPfad = False Then
            Pfad = DataSettings.Resourcenpfad + "Maps"
            Pfad = IO.Path.Combine(Pfad, Name + Endung)
        End If

        If Pfad.ToLower.EndsWith(".sav") Then Pfad = Pfad.Replace("\Maps\", "\Savegames\")

        If Hauptmenue.AufzeichnungAktiv Then
            Hauptmenue.AufzeichnungSichern(Pfad.Replace("\Savegames\", "\Record\active\").Replace(".sav", ".rpl"))
            Spielfeld.MapPosition = Pfad.Replace("\Savegames\", "\Record\active\").Replace(".sav", ".rpl")
        End If
        'Bei Spielstaenden sollte die Landschaften fest gemacht werden. Klasse Deutsch Was?
        If Endung = ".sav" Then
            For I = 0 To 1
                For X = 0 To Spielfeld.Breite - 1
                    For Y = 0 To Spielfeld.Hoehe - 1
                        Spielfeld.Landschaften(X, Y, I).BildIDFest = True
                    Next
                Next
            Next
        End If
        'Well now we start to Save the Map
        'Header:
        If My.Computer.FileSystem.FileExists(Pfad) Then My.Computer.FileSystem.DeleteFile(Pfad)


        Dim StrW As New Filestream(Pfad, IO.FileMode.OpenOrCreate, IO.FileAccess.Write)
        StrW.WriteByte(CharToByte("C"))
        StrW.WriteByte(CharToByte("o"))
        StrW.WriteByte(CharToByte("W"))
        StrW.WriteByte(CharToByte("M"))
        StrW.WriteByte(CharToByte("a"))
        StrW.WriteByte(CharToByte("p"))
        StrW.WriteByte(GameHeaderVersion)
        'Write Width and Heigth
        Dim B As Byte() = IntToBytes(Spielfeld.Breite)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        B = IntToBytes(Spielfeld.Hoehe)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        StrW.WriteByte(Spielfeld.MomentaneSchlacht)
        B = IntToBytes(Spielfeld.Spieler.Length - 1)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        If Spielfeld.Game_Timer Is Nothing Or Spielfeld.Regeln.Rundenzeit <= 0 Then
            StrW.WriteByte(0)
        Else
            StrW.WriteByte(1)
            For I = 0 To Spielfeld.Game_Timer.Length - 1
                Spielfeld.Game_Timer(I).Write(StrW)
            Next
            StrW.WriteByte(254)
            StrW.WriteByte(254)
            StrW.WriteByte(254)
            StrW.WriteByte(254)
        End If
        Dim Terrains As New List(Of String)
        Dim Units As New List(Of String)
        Dim Buildings As New List(Of String)
        For I = 0 To 1
            For X = 0 To Spielfeld.Breite - 1
                For Y = 0 To Spielfeld.Hoehe - 1
                    If Not Terrains.Contains(Spielfeld.Landschaften(X, Y, I).LandschaftsID) Then
                        Terrains.Add(Spielfeld.Landschaften(X, Y, I).LandschaftsID)
                    End If
                    If Spielfeld.Einheiten(X, Y, I) IsNot Nothing Then
                        If Not Units.Contains(Spielfeld.Einheiten(X, Y, I).EinheitenID) Then
                            Units.Add(Spielfeld.Einheiten(X, Y, I).EinheitenID)
                        End If
                        If Spielfeld.Einheiten(X, Y, I).HasLadung Then
                            For I2 = 0 To Spielfeld.Einheiten(X, Y, I).Ladung.Length - 1
                                If Spielfeld.Einheiten(X, Y, I).Ladung(I2) IsNot Nothing Then
                                    If Not Units.Contains(Spielfeld.Einheiten(X, Y, I).Ladung(I2).EinheitenID) Then
                                        Units.Add(Spielfeld.Einheiten(X, Y, I).Ladung(I2).EinheitenID)
                                    End If
                                    If Spielfeld.Einheiten(X, Y, I).Ladung(I2).HasLadung Then
                                        For I3 = 0 To Spielfeld.Einheiten(X, Y, I).Ladung(I2).Ladung.Length - 1
                                            If Spielfeld.Einheiten(X, Y, I).Ladung(I2).Ladung IsNot Nothing Then
                                                If Not Units.Contains(Spielfeld.Einheiten(X, Y, I).Ladung(I2).Ladung(I3).EinheitenID) Then
                                                    Units.Add(Spielfeld.Einheiten(X, Y, I).Ladung(I2).Ladung(I3).EinheitenID)
                                                End If
                                            End If
                                        Next
                                    End If
                                End If
                            Next
                        End If
                    End If
                    If Spielfeld.Landschaften(X, Y, I).Gebaeude IsNot Nothing Then
                        If Spielfeld.Landschaften(X, Y, I).Gebaeude.GetRealGebaeudeID <> "VERWEIS" Then
                            If Not Buildings.Contains(Spielfeld.Landschaften(X, Y, I).Gebaeude.GebaeudeID) Then
                                Buildings.Add(Spielfeld.Landschaften(X, Y, I).Gebaeude.GebaeudeID)
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Dim Landschaften As String() = Terrains.ToArray
        WriteStringArray(StrW, Landschaften)
        WriteStringArray(StrW, Buildings.ToArray)
        WriteStringArray(StrW, Units.ToArray)
        'Player Info
        For I = 1 To Spielfeld.Spieler.Length - 1
            SavePlayer(StrW, Spielfeld.Spieler(I))
        Next
        Spielfeld.Regeln.Write(StrW, Spielfeld.Spieler.Length - 1)
        'Still Map Header Stuff:
        StrW.WriteByte(Spielfeld.EingabenErlauben)
        B = IntToBytes(Spielfeld.BildschirmKooX)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        B = IntToBytes(Spielfeld.BildschirmKooY)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        WriteVector3(StrW, Spielfeld.KameraPos)
        WriteVector3(StrW, Spielfeld.KameraTarget)
        B = SingletoBytes(Spielfeld.KameraVerhaeltnisWeite)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        B = SingletoBytes(Spielfeld.KameraHoehe)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        B = SingletoBytes(Spielfeld.KameraRichtung)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        WriteString(StrW, Spielfeld.Kartenname)
        WriteString(StrW, Spielfeld.Beschreibung)
        WriteString(StrW, Spielfeld.Autor)
        B = IntToBytes(Spielfeld.Runde)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        B = IntToBytes(Spielfeld.StartRechteck.X)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        B = IntToBytes(Spielfeld.StartRechteck.Y)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        B = IntToBytes(Spielfeld.StartRechteck.Width)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        B = IntToBytes(Spielfeld.StartRechteck.Height)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        WriteString(StrW, Spielfeld.MapPosition)
        If Spielfeld.AktuellerSpieler IsNot Nothing Then
            B = IntToBytes(Spielfeld.AktuellerSpieler.Spieler)
        Else
            B = IntToBytes(0)
        End If
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        StrW.WriteByte(Spielfeld.CommanderWarsModus)
        WriteString(StrW, Spielfeld.NaechsteKarte)
        WriteString(StrW, Spielfeld.DieseKarte)
        WriteString(StrW, ObjektScript.ScriptName)
        If Spielfeld.Scripts IsNot Nothing Then
            StrW.WriteByte(1)
            For I = 0 To Spielfeld.Scripts.Length - 1
                Spielfeld.Scripts(I).Write(StrW)
            Next
            StrW.WriteByte(254)
            StrW.WriteByte(254)
            StrW.WriteByte(254)
            StrW.WriteByte(254)
        Else
            StrW.WriteByte(0)
        End If
        For I = 0 To ObjektScript.Variablen.Count - 1
            ObjektScript.Variablen(I).Write(StrW)
        Next
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        If Spielfeld.Aufzeichnung Is Nothing Then
            StrW.WriteByte(0)
        Else
            StrW.WriteByte(1)
            Spielfeld.Aufzeichnung.Write(StrW)
        End If
        If Spielfeld.ObjektLandkartenInfo Is Nothing Then
            StrW.WriteByte(0)
        Else
            StrW.WriteByte(1)
            Spielfeld.ObjektLandkartenInfo.Write(StrW)
        End If

        'Now saving Terrain
        For I = 0 To 1
            For X = 0 To Spielfeld.Breite - 1
                For Y = 0 To Spielfeld.Hoehe - 1
                    Spielfeld.Landschaften(X, Y, I).Write(StrW, I, Landschaften)
                Next
            Next
        Next
        'Now saving Buildings
        For I = 0 To 1
            For X = 0 To Spielfeld.Breite - 1
                For Y = 0 To Spielfeld.Hoehe - 1
                    If Spielfeld.Landschaften(X, Y, I).Gebaeude IsNot Nothing Then
                        If Spielfeld.Landschaften(X, Y, I).Gebaeude.GetRealGebaeudeID <> "VERWEIS" Then
                            Spielfeld.Landschaften(X, Y, I).Gebaeude.Write(StrW, X, Y, I, Buildings)
                        End If
                    End If
                Next
            Next
        Next
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        'Now saving Units
        For I = 0 To 1
            For X = 0 To Spielfeld.Breite - 1
                For Y = 0 To Spielfeld.Hoehe - 1
                    If Spielfeld.Einheiten(X, Y, I) IsNot Nothing Then
                        Spielfeld.Einheiten(X, Y, I).Write(StrW, X, Y, I, Units)
                    End If
                Next
            Next
        Next
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.Close()
        If Endung = ".sav" Then
            DataSettings.LetztesSpiel = Pfad
            DataSettings.MySettingsIniSave()
        End If
    End Sub
    Public Function LoadMap(ByRef Pfad As String) As ObjektSpielfeld
        If My.Computer.FileSystem.FileExists(Pfad) Then
            'read Header.
            Dim StrR As New Filestream(Pfad, IO.FileMode.Open, IO.FileAccess.Read)
            If ByteToChar(StrR.ReadByte) = "C" Then
                If ByteToChar(StrR.ReadByte) = "o" Then
                    If ByteToChar(StrR.ReadByte) = "W" Then
                        If ByteToChar(StrR.ReadByte) = "M" Then
                            If ByteToChar(StrR.ReadByte) = "a" Then
                                If ByteToChar(StrR.ReadByte) = "p" Then
                                    Dim HeaderVersion As Byte = StrR.ReadByte
                                    'It's a CoW Map
                                    Dim Spielfeld As ObjektSpielfeld = Nothing
                                    'Read High and Width
                                    Dim Breite As Integer = 0
                                    Dim Hoehe As Integer = 0
                                    Dim MomentaneSchlacht As Integer = 0
                                    Dim Spieler As Integer
                                    Dim B(3) As Byte
                                    For I = 0 To 3
                                        B(I) = StrR.ReadByte
                                    Next
                                    Breite = BytesToInt(B)
                                    For I = 0 To 3
                                        B(I) = StrR.ReadByte
                                    Next
                                    Hoehe = BytesToInt(B)
                                    MomentaneSchlacht = StrR.ReadByte
                                    For I = 0 To 3
                                        B(I) = StrR.ReadByte
                                    Next
                                    Spieler = BytesToInt(B)
                                    Dim Exists As Byte = StrR.ReadByte
                                    Dim Ende() As Byte = {0, 0, 0, 0}
                                    Dim Game_Timer(Spieler) As Timer
                                    Dim Counter As Integer = 0
                                    If Exists = 1 Then
                                        While Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254)
                                            Ende(0) = StrR.ReadByte
                                            Ende(1) = StrR.ReadByte
                                            Ende(2) = StrR.ReadByte
                                            Ende(3) = StrR.ReadByte
                                            StrR.Seek(-4)
                                            If Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254) Then
                                                Game_Timer(Counter).Read(StrR)
                                                Counter += 1
                                            End If
                                        End While
                                        StrR.ReadByte()
                                        StrR.ReadByte()
                                        StrR.ReadByte()
                                        StrR.ReadByte()
                                    Else
                                        For I = 0 To Spieler
                                            Game_Timer(I) = New Timer(0, Timer.Timemodus.Single_Countdown)
                                        Next
                                    End If
                                    Dim Terrains() As String = ReadStringArray(StrR)
                                    Dim Buildings() As String = ReadStringArray(StrR)
                                    Dim Units() As String = ReadStringArray(StrR)

                                    Dim Player(Spieler) As ObjektSpieler
                                    Player(0) = New ObjektSpieler(0, Hauptmenue.SpielerNeutral, 0, New ObjektKO() {New KOAndy(0), Nothing}, 0, Armeen.OS.ToString, "", Nothing, ObjektSpieler.KIStufen.Kinderleicht, 0)
                                    For I = 1 To Spieler
                                        Player(I) = LoadPlayer(StrR, I)
                                    Next

                                    Spielfeld = New ObjektSpielfeld(Breite, Hoehe, Player, New ObjektRegeln(StrR, Spieler), False)

                                    Spielfeld.Game_Timer = Game_Timer
                                    Spielfeld.MomentaneSchlacht = MomentaneSchlacht
                                    Spielfeld.EingabenErlauben = StrR.ReadByte
                                    For I = 0 To B.Length - 1
                                        B(I) = StrR.ReadByte
                                    Next
                                    Spielfeld.BildschirmKooX = BytesToInt(B)
                                    For I = 0 To B.Length - 1
                                        B(I) = StrR.ReadByte
                                    Next
                                    Spielfeld.BildschirmKooY = BytesToInt(B)
                                    Spielfeld.KameraPos = ReadVector3(StrR)
                                    Spielfeld.KameraTarget = ReadVector3(StrR)
                                    For I = 0 To B.Length - 1
                                        B(I) = StrR.ReadByte
                                    Next
                                    Spielfeld.KameraVerhaeltnisWeite = BytesToSingle(B)
                                    For I = 0 To B.Length - 1
                                        B(I) = StrR.ReadByte
                                    Next
                                    Spielfeld.KameraHoehe = BytesToSingle(B)
                                    For I = 0 To B.Length - 1
                                        B(I) = StrR.ReadByte
                                    Next
                                    Spielfeld.KameraRichtung = BytesToSingle(B)
                                    Spielfeld.Kartenname = ReadString(StrR)
                                    Spielfeld.Beschreibung = ReadString(StrR)
                                    Spielfeld.Autor = ReadString(StrR)
                                    For I = 0 To B.Length - 1
                                        B(I) = StrR.ReadByte
                                    Next
                                    Spielfeld.SetRunde(BytesToInt(B))
                                    For I = 0 To B.Length - 1
                                        B(I) = StrR.ReadByte
                                    Next
                                    Spielfeld.StartRechteck.X = BytesToInt(B)
                                    For I = 0 To B.Length - 1
                                        B(I) = StrR.ReadByte
                                    Next
                                    Spielfeld.StartRechteck.Y = BytesToInt(B)
                                    For I = 0 To B.Length - 1
                                        B(I) = StrR.ReadByte
                                    Next
                                    Spielfeld.StartRechteck.Width = BytesToInt(B)
                                    For I = 0 To B.Length - 1
                                        B(I) = StrR.ReadByte
                                    Next
                                    Spielfeld.StartRechteck.Height = BytesToInt(B)
                                    Spielfeld.MapPosition = ReadString(StrR)
                                    For I = 0 To B.Length - 1
                                        B(I) = StrR.ReadByte
                                    Next
                                    Dim AktSpieler As Integer = BytesToInt(B)
                                    If AktSpieler > 0 And AktSpieler < Spielfeld.Spieler.Length Then
                                        Spielfeld.AktuellerSpieler = Spielfeld.Spieler(AktSpieler)
                                    End If
                                    Spielfeld.CommanderWarsModus = StrR.ReadByte
                                    Spielfeld.NaechsteKarte = ReadString(StrR)
                                    Spielfeld.DieseKarte = ReadString(StrR)
                                    'Loading Script Still Header
                                    ObjektScript.ScriptName = ReadString(StrR)
                                    Exists = StrR.ReadByte
                                    Ende = New Byte() {0, 0, 0, 0}
                                    If Exists = 1 Then
                                        While Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254)
                                            Ende(0) = StrR.ReadByte
                                            Ende(1) = StrR.ReadByte
                                            Ende(2) = StrR.ReadByte
                                            Ende(3) = StrR.ReadByte
                                            StrR.Seek(-4)
                                            If Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254) Then
                                                Array.Resize(Spielfeld.Scripts, Spielfeld.Scripts.Length + 1)
                                                Spielfeld.Scripts(Spielfeld.Scripts.Length - 1) = New ObjektScript()
                                                Spielfeld.Scripts(Spielfeld.Scripts.Length - 1).Read(StrR)
                                            End If
                                        End While
                                        StrR.ReadByte()
                                        StrR.ReadByte()
                                        StrR.ReadByte()
                                        StrR.ReadByte()

                                    End If
                                    Ende = New Byte() {0, 0, 0, 0}
                                    While Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254)
                                        Ende(0) = StrR.ReadByte
                                        Ende(1) = StrR.ReadByte
                                        Ende(2) = StrR.ReadByte
                                        Ende(3) = StrR.ReadByte
                                        StrR.Seek(-4)
                                        If Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254) Then
                                            ObjektScript.Variablen.Add(New ObjektGebaeude.Variable)
                                            ObjektScript.Variablen(ObjektScript.Variablen.Count - 1).read(StrR)
                                        End If
                                    End While
                                    StrR.ReadByte()
                                    StrR.ReadByte()
                                    StrR.ReadByte()
                                    StrR.ReadByte()
                                    Exists = StrR.ReadByte
                                    If Exists = 1 Then
                                        Spielfeld.Aufzeichnung = New ObjektAufzeichnungen(0)
                                        Spielfeld.Aufzeichnung.Read(StrR, Spieler)
                                    End If
                                    Exists = StrR.ReadByte
                                    If Exists = 1 Then
                                        Spielfeld.ObjektLandkartenInfo = New ObjektLandkartenInfos()
                                        Spielfeld.ObjektLandkartenInfo.Read(StrR)
                                    End If
                                    'Now Loading Terrain
                                    For I = 0 To 1
                                        For X = 0 To Spielfeld.Breite - 1
                                            For Y = 0 To Spielfeld.Hoehe - 1
                                                ObjektLandschaft.Read(StrR, X, Y, I, Spielfeld, Terrains)
                                            Next
                                        Next
                                    Next
                                    'Now loading Buildings
                                    Ende = New Byte() {0, 0, 0, 0}
                                    While Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254)
                                        Ende(0) = StrR.ReadByte
                                        Ende(1) = StrR.ReadByte
                                        Ende(2) = StrR.ReadByte
                                        Ende(3) = StrR.ReadByte
                                        StrR.Seek(-4)
                                        If Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254) Then
                                            ObjektGebaeude.Read(StrR, Spielfeld, Buildings)
                                        End If
                                    End While
                                    StrR.ReadByte()
                                    StrR.ReadByte()
                                    StrR.ReadByte()
                                    StrR.ReadByte()
                                    'Now Loading Units 
                                    Ende = New Byte() {0, 0, 0, 0}
                                    While Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254)
                                        Ende(0) = StrR.ReadByte
                                        Ende(1) = StrR.ReadByte
                                        Ende(2) = StrR.ReadByte
                                        Ende(3) = StrR.ReadByte
                                        StrR.Seek(-4)
                                        If Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254) Then
                                            Dim Schlacht As Integer
                                            Dim E As ObjektEinheit = ObjektEinheit.Read(StrR, Units, Schlacht)
                                            Spielfeld.Einheiten(E.X, E.Y, Schlacht) = E
                                        End If
                                    End While
                                    StrR.ReadByte()
                                    StrR.ReadByte()
                                    StrR.ReadByte()
                                    StrR.ReadByte()

                                    StrR.Close()
                                    'Loading Verweis
                                    For I = 0 To 1
                                        For X = 0 To Spielfeld.Breite - 1
                                            For Y = 0 To Spielfeld.Hoehe - 1
                                                If Spielfeld.Landschaften(X, Y, I).Gebaeude IsNot Nothing Then

                                                    If Spielfeld.Landschaften(X, Y, I).Gebaeude.Verweisgebaeude IsNot Nothing Then
                                                        For I2 = 0 To Spielfeld.Landschaften(X, Y, I).Gebaeude.Verweisgebaeude.GetLength(0) - 1
                                                            Spielfeld.Landschaften(X + Spielfeld.Landschaften(X, Y, I).Gebaeude.Verweisgebaeude(I2, 0), Y + Spielfeld.Landschaften(X, Y, I).Gebaeude.Verweisgebaeude(I2, 1), I).Gebaeude = New GebaeudeVerweis(Spielfeld.Landschaften(X, Y, I).Gebaeude.Spieler, X, Y, I)
                                                        Next
                                                    End If
                                                End If
                                            Next
                                        Next
                                    Next
                                    For I = 1 To Spielfeld.Spieler.Length - 1
                                        If Spielfeld.Spieler(I).ExternGezogeneEinheiten IsNot Nothing Then
                                            For I2 = 1 To Spielfeld.Spieler(I).ExternGezogeneEinheiten.Length - 1
                                                Spielfeld.Spieler(I).ExternGezogeneEinheiten(I2).Einheit = Spielfeld.Einheiten(Spielfeld.Spieler(I).ExternGezogeneEinheiten(I2).Einheit.X, Spielfeld.Spieler(I).ExternGezogeneEinheiten(I2).Einheit.Y, Spielfeld.Spieler(I).ExternGezogeneEinheiten(I2).Einheit.Spieler)
                                            Next
                                        End If
                                    Next
                                    'Loading CO's that are unset
                                    For I = 0 To Spielfeld.Spieler.Length - 1
                                        If Spielfeld.Spieler(I).KOS(0) Is Nothing Then
                                            Spielfeld.Spieler(I).KOS = Nothing
                                        End If
                                    Next

                                    Return Spielfeld
                                End If
                            End If
                        End If
                    End If
                End If
            End If
            StrR.Close()
        End If
        Return Nothing
    End Function
#Region "Byte Converter"
    Public Function IntToBytes(ByVal Int As Integer) As Byte()
        Return BitConverter.GetBytes(Int)
    End Function
    Public Function BytesToInt(ByVal B As Byte()) As Integer
        Return BitConverter.ToInt32(B, 0)
    End Function
    Public Function UInt64ToBytes(ByVal Int As UInt64) As Byte()
        Return BitConverter.GetBytes(Int)
    End Function
    Public Function BytesToUInt64(ByVal B As Byte()) As UInt64
        Return BitConverter.ToUInt64(B, 0)
    End Function
    Public Function LongToBytes(ByVal L As Long) As Byte()
        Return BitConverter.GetBytes(L)
    End Function
    Public Function BytesToLong(ByVal B As Byte()) As Long
        Return BitConverter.ToInt64(B, 0)
    End Function
    Public Function SingletoBytes(ByVal S As Single) As Byte()
        Return BitConverter.GetBytes(S)
    End Function
    Public Function BytesToSingle(ByVal B As Byte()) As Single
        Return BitConverter.ToSingle(B, 0)
    End Function
    Public Function DoubleToBytes(ByVal S As Double) As Byte()
        Return BitConverter.GetBytes(S)
    End Function
    Public Function BytesToDouble(ByVal B As Byte()) As Double
        Return BitConverter.ToDouble(B, 0)
    End Function
    Public Function CharToByte(ByVal C As Char) As Byte
        Return BitConverter.GetBytes(C)(0)
    End Function
    Public Function ByteToChar(ByVal B As Byte) As Char
        Return BitConverter.ToChar(New Byte() {B, 0}, 0)
    End Function
    Public Sub WriteString(ByRef StrW As Filestream, ByVal S As String)
        If S Is Nothing Then S = ""
        Dim C() As Char = S.ToCharArray
        For I = 0 To C.Length - 1
            StrW.WriteByte(CharToByte(C(I)))
        Next
        StrW.WriteByte(0)
    End Sub
    Public Function ReadString(ByRef StrR As Filestream) As String
        Dim S As String = ""
        Dim B As Byte = StrR.ReadByte
        Dim B1 As Byte = 0
        While B <> B1 'Terminator
            S += ByteToChar(B)
            B = StrR.ReadByte
        End While
        Return S
    End Function
    Public Function ColorToByte(ByVal Farbe As Color) As Byte()
        Return New Byte() {Farbe.A, Farbe.R, Farbe.G, Farbe.B}
    End Function
    Public Function BytesToColor(ByVal B As Byte()) As Color
        Return Color.FromArgb(B(0), B(1), B(2), B(3))
    End Function
    Public Sub WriteBauliste(ByRef StrW As Filestream, ByVal Tabelle As Bauliste)
        WriteStringArray(StrW, Tabelle.Beschreibung)
        WriteIntegerArray(StrW, Tabelle.Werte)
    End Sub
    Public Function ReadBauliste(ByRef StrR As Filestream) As Bauliste
        Dim Namen() As String = ReadStringArray(StrR)
        Dim Werte() As Integer = ReadIntegerArray(StrR)
        Return New Bauliste(Werte, Namen)
    End Function
    Public Sub WriteStringArray(ByRef StrW As Filestream, ByVal Arra() As String)
        For I = 0 To Arra.Length - 1
            WriteString(StrW, Arra(I))
        Next
        StrW.WriteByte(1)
    End Sub
    Public Function ReadStringArray(ByRef StrR As Filestream) As String()
        Dim Arra() As String = {}
        Dim Ende As Byte = 0
        While Ende <> 1
            Ende = StrR.ReadByte
            StrR.Seek(-1)
            If Ende <> 1 Then
                Array.Resize(Arra, Arra.Length + 1)
                Arra(Arra.Length - 1) = ReadString(StrR)
            End If
        End While
        StrR.ReadByte()
        Return Arra
    End Function
    Public Sub WriteIntegerArray(ByRef StrW As Filestream, ByVal Arra() As Integer)
        Dim B(3) As Byte
        For I = 0 To Arra.Length - 1
            B = IntToBytes(Arra(I))
            For I2 = 0 To B.Length - 1
                StrW.WriteByte(B(I2))
            Next
        Next
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
    End Sub
    Public Function ReadIntegerArray(ByRef StrR As Filestream) As Integer()
        Dim Arra() As Integer = {}
        Dim B(3) As Byte
        Dim Ende() As Byte = {0, 0, 0, 0}
        While Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254)
            Ende(0) = StrR.ReadByte
            Ende(1) = StrR.ReadByte
            Ende(2) = StrR.ReadByte
            Ende(3) = StrR.ReadByte
            StrR.Seek(-4)
            If Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254) Then
                Array.Resize(Arra, Arra.Length + 1)
                For I = 0 To B.Length - 1
                    B(I) = StrR.ReadByte
                Next
                Arra(Arra.Length - 1) = BytesToInt(B)
            End If
        End While
        StrR.ReadByte()
        StrR.ReadByte()
        StrR.ReadByte()
        StrR.ReadByte()
        Return Arra
    End Function
    Public Sub WriteBooleanArray(ByRef StrW As Filestream, ByVal Arra() As Boolean)
        For I = 0 To Arra.Length - 1
            StrW.WriteByte(CByte(Arra(I)))
        Next
        StrW.WriteByte(200)
    End Sub
    Public Function ReadBooleanArray(ByRef StrR As Filestream) As Boolean()
        Dim Arra() As Boolean = {}
        Dim Ende As Byte = 0
        While Not (Ende = 200)
            Ende = StrR.ReadByte
            StrR.Seek(-1)
            If Not (Ende = 200) Then
                Array.Resize(Arra, Arra.Length + 1)
                Arra(Arra.Length - 1) = StrR.ReadByte
            End If
        End While
        StrR.ReadByte()
        Return Arra
    End Function
    Public Sub WriteUInteger64Array(ByRef StrW As Filestream, ByVal Arra() As UInt64)
        Dim B(7) As Byte
        For I = 0 To Arra.Length - 1
            B = UInt64ToBytes(Arra(I))
            For I2 = 0 To B.Length - 1
                StrW.WriteByte(B(I2))
            Next
        Next
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
    End Sub
    Public Function ReadUInteger64Array(ByRef StrR As Filestream) As UInt64()
        Dim Arra() As UInt64 = {}
        Dim B(7) As Byte
        Dim Ende() As Byte = {0, 0, 0, 0}
        While Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254)
            Ende(0) = StrR.ReadByte
            Ende(1) = StrR.ReadByte
            Ende(2) = StrR.ReadByte
            Ende(3) = StrR.ReadByte
            StrR.Seek(-4)
            If Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254) Then
                Array.Resize(Arra, Arra.Length + 1)
                For I = 0 To B.Length - 1
                    B(I) = StrR.ReadByte
                Next
                Arra(Arra.Length - 1) = BytesToUInt64(B)
            End If
        End While
        StrR.ReadByte()
        StrR.ReadByte()
        StrR.ReadByte()
        StrR.ReadByte()
        Return Arra
    End Function
    Public Sub WriteVec4Array(ByRef StrW As Filestream, ByVal Arra() As Vector4)
        Dim B(3) As Byte
        For I = 0 To Arra.Length - 1
            WriteVector4(StrW, Arra(I))
        Next
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
    End Sub
    Public Function ReadVec4Array(ByRef StrR As Filestream) As Vector4()
        Dim Arra() As Vector4 = {}
        Dim Ende() As Byte = {0, 0, 0, 0}
        While Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254)
            Ende(0) = StrR.ReadByte
            Ende(1) = StrR.ReadByte
            Ende(2) = StrR.ReadByte
            Ende(3) = StrR.ReadByte
            StrR.Seek(-4)
            If Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254) Then
                Array.Resize(Arra, Arra.Length + 1)
                Arra(Arra.Length - 1) = ReadVector4(StrR)
            End If
        End While
        StrR.ReadByte()
        StrR.ReadByte()
        StrR.ReadByte()
        StrR.ReadByte()
        Return Arra
    End Function
    Public Sub WriteVector4(ByRef StrW As Filestream, ByVal Vec4 As Vector4)
        Dim B(3) As Byte
        B = SingletoBytes(Vec4.X)
        For I2 = 0 To B.Length - 1
            StrW.WriteByte(B(I2))
        Next
        B = SingletoBytes(Vec4.Y)
        For I2 = 0 To B.Length - 1
            StrW.WriteByte(B(I2))
        Next
        B = SingletoBytes(Vec4.Z)
        For I2 = 0 To B.Length - 1
            StrW.WriteByte(B(I2))
        Next
        B = SingletoBytes(Vec4.W)
        For I2 = 0 To B.Length - 1
            StrW.WriteByte(B(I2))
        Next
    End Sub
    Public Function ReadVector4(ByRef StrR As Filestream) As Vector4
        Dim Vec4 As New Vector4
        Dim B(3) As Byte
        For I = 0 To B.Length - 1
            B(I) = StrR.ReadByte
        Next
        Vec4.X = BytesToSingle(B)
        For I = 0 To B.Length - 1
            B(I) = StrR.ReadByte
        Next
        Vec4.Y = BytesToSingle(B)
        For I = 0 To B.Length - 1
            B(I) = StrR.ReadByte
        Next
        Vec4.Z = BytesToSingle(B)
        For I = 0 To B.Length - 1
            B(I) = StrR.ReadByte
        Next
        Vec4.W = BytesToSingle(B)
        Return Vec4
    End Function
    Public Sub WriteVec3Array(ByRef StrW As Filestream, ByVal Arra() As Vector3)
        Dim B(3) As Byte
        For I = 0 To Arra.Length - 1
            WriteVector3(StrW, Arra(I))
        Next
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
        StrW.WriteByte(254)
    End Sub
    Public Function ReadVec3Array(ByRef StrR As Filestream) As Vector3()
        Dim Arra() As Vector3 = {}
        Dim Ende() As Byte = {0, 0, 0, 0}
        While Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254)
            Ende(0) = StrR.ReadByte
            Ende(1) = StrR.ReadByte
            Ende(2) = StrR.ReadByte
            Ende(3) = StrR.ReadByte
            StrR.Seek(-4)
            If Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254) Then
                Array.Resize(Arra, Arra.Length + 1)
                Arra(Arra.Length - 1) = ReadVector3(StrR)
            End If
        End While
        StrR.ReadByte()
        StrR.ReadByte()
        StrR.ReadByte()
        StrR.ReadByte()
        Return Arra
    End Function
    Public Sub WriteVector3(ByRef StrW As Filestream, ByVal Vec3 As Vector3)
        Dim B(3) As Byte
        B = SingletoBytes(Vec3.X)
        For I2 = 0 To B.Length - 1
            StrW.WriteByte(B(I2))
        Next
        B = SingletoBytes(Vec3.Y)
        For I2 = 0 To B.Length - 1
            StrW.WriteByte(B(I2))
        Next
        B = SingletoBytes(Vec3.Z)
        For I2 = 0 To B.Length - 1
            StrW.WriteByte(B(I2))
        Next
    End Sub
    Public Function ReadVector3(ByRef StrR As Filestream) As Vector3
        Dim Vec3 As New Vector3
        Dim B(3) As Byte
        For I = 0 To B.Length - 1
            B(I) = StrR.ReadByte
        Next
        Vec3.X = BytesToSingle(B)
        For I = 0 To B.Length - 1
            B(I) = StrR.ReadByte
        Next
        Vec3.Y = BytesToSingle(B)
        For I = 0 To B.Length - 1
            B(I) = StrR.ReadByte
        Next
        Vec3.Z = BytesToSingle(B)
        Return Vec3
    End Function
#End Region
    Private Sub SavePlayer(ByRef StrW As Filestream, ByVal Spieler As ObjektSpieler)
        StrW.WriteByte(SpielerVersion)
        'number of CO's
        If Spieler.KOS IsNot Nothing Then
            If Spieler.KOS(0) Is Nothing Then
                StrW.WriteByte(0)
            Else
                If Spieler.KOS(1) Is Nothing Then
                    StrW.WriteByte(1)
                Else
                    StrW.WriteByte(2)
                End If
            End If
        Else
            StrW.WriteByte(0)
        End If
        Dim B As Byte() = ColorToByte(Spieler.Farbe)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        'Save Fonds per City
        B = IntToBytes(Spieler.FondsproStadt)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        'Startfonds
        B = IntToBytes(Spieler.Fonds)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        'Army
        Try
            StrW.WriteByte(CByte([Enum].Parse(Armeen.OS.GetType, Spieler.Armee)))
        Catch
            StrW.WriteByte(CByte(Armeen.OS))
        End Try
        'Team
        StrW.WriteByte(CharToByte(Spieler.Team))
        'KI
        StrW.WriteByte(CByte(Spieler.KIStufe))
        'Fabrikfonds
        B = IntToBytes(Spieler.Fabrikfonds)
        For I = 0 To B.Length - 1
            StrW.WriteByte(B(I))
        Next
        'Bauliste
        WriteBauliste(StrW, Spieler.GetBauliste)
        'Gabeleiste
        StrW.WriteByte(Spieler.Gabeleiste)
        'AI-Setup
        StrW.WriteByte(Spieler.NeutraleGebaeudeAngriff)
        'Playername
        WriteString(StrW, Spieler.Spielername)
        'Sichtfelder
        WriteVec4Array(StrW, Spieler.Sichtfelder)
        'Veraenderte Werte
        Spieler.VeraenderteWerte.Write(StrW)
        'AI Auto Building
        If Spieler.Bauprioritaeten Is Nothing Then
            StrW.WriteByte(0)
        ElseIf Spieler.Bauprioritaeten.IsClear Then
            StrW.WriteByte(0)
        Else
            StrW.WriteByte(1)
            Spieler.Bauprioritaeten.Write(StrW)
        End If
        'Write CO's
        If Spieler.KOS IsNot Nothing Then
            If Spieler.KOS(0) IsNot Nothing Then
                Spieler.KOS(0).Write(StrW)
                If Spieler.KOS(1) IsNot Nothing Then
                    Spieler.KOS(1).Write(StrW)
                End If
            End If
        End If
        If Spieler.ExternGezogeneEinheiten IsNot Nothing Then
            If Spieler.ExternGezogeneEinheiten.Length > 0 Then
                StrW.WriteByte(1)
                For I = 0 To Spieler.ExternGezogeneEinheiten.Length - 1
                    Spieler.ExternGezogeneEinheiten(I).Write(StrW)
                Next
                StrW.WriteByte(254)
                StrW.WriteByte(254)
                StrW.WriteByte(254)
                StrW.WriteByte(254)
            Else
                StrW.WriteByte(0)
            End If
        Else
            StrW.WriteByte(0)
        End If
    End Sub
    Private Function LoadPlayer(ByRef StrR As Filestream, ByVal Spieler As Integer) As ObjektSpieler
        Dim Playerversion As Byte = StrR.ReadByte
        Dim B(3) As Byte
        Dim NumberOfCOs As Integer = StrR.ReadByte()
        'Player Color
        Dim Farbe As Color
        For I = 0 To B.Length - 1
            B(I) = StrR.ReadByte
        Next
        Farbe = BytesToColor(B)
        'Load Fonds
        Dim FondsProStadt As Integer
        For I = 0 To B.Length - 1
            B(I) = StrR.ReadByte
        Next
        FondsProStadt = BytesToInt(B)
        Dim Startfonds As Integer
        For I = 0 To B.Length - 1
            B(I) = StrR.ReadByte
        Next
        Startfonds = BytesToInt(B)
        Dim Armee As String = [Enum].GetName(Armeen.OS.GetType, StrR.ReadByte)
        Dim Team As String = ByteToChar(StrR.ReadByte)
        Dim KI As ObjektSpieler.KIStufen = StrR.ReadByte
        Dim Fabrikfonds As Integer
        For I = 0 To B.Length - 1
            B(I) = StrR.ReadByte
        Next
        Fabrikfonds = BytesToInt(B)
        Dim Bautabelle As ObjektTabelle = ReadBauliste(StrR)


        Dim Player As New ObjektSpieler(Spieler, Farbe, FondsProStadt, Nothing, Startfonds, Armee, Team, Bautabelle, KI, Fabrikfonds)
        Player.Gabeleiste = StrR.ReadByte
        Player.NeutraleGebaeudeAngriff = StrR.ReadByte
        Player.Spielername = ReadString(StrR)
        Player.Sichtfelder = ReadVec4Array(StrR)
        Player.VeraenderteWerte.Read(StrR) 'selfreading sub LOL
        'AI Auto Building
        If StrR.ReadByte = 1 Then
            Player.Bauprioritaeten = New KIGenerellerSuperBau.PrioritaetsBau(KIGenerellerSuperBau.PrioritaetsBau.Prioritaeten.Normal, KIGenerellerSuperBau.PrioritaetsBau.Prioritaeten.Normal, KIGenerellerSuperBau.PrioritaetsBau.Prioritaeten.Normal, KIGenerellerSuperBau.PrioritaetsBau.Prioritaeten.Normal, KIGenerellerSuperBau.PrioritaetsBau.Prioritaeten.Normal, KIGenerellerSuperBau.PrioritaetsBau.Prioritaeten.Normal, KIGenerellerSuperBau.PrioritaetsBau.Prioritaeten.Normal, 0, 0, False)
            Player.Bauprioritaeten.Read(StrR)
        End If
        ReDim Player.KOS(1)
        For I = 1 To NumberOfCOs
            Player.KOS(I - 1) = ObjektKO.Read(StrR)
        Next
        Dim Exists As Byte = StrR.ReadByte
        Dim Ende() As Byte = {0, 0, 0, 0}
        If Exists = 1 Then
            While Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254)
                Ende(0) = StrR.ReadByte
                Ende(1) = StrR.ReadByte
                Ende(2) = StrR.ReadByte
                Ende(3) = StrR.ReadByte
                StrR.Seek(-4)
                If Not (Ende(0) = 254 And Ende(1) = 254 And Ende(2) = 254 And Ende(3) = 254) Then
                    Array.Resize(Player.ExternGezogeneEinheiten, Player.ExternGezogeneEinheiten.Length + 1)
                    Player.ExternGezogeneEinheiten(Player.ExternGezogeneEinheiten.Length - 1).Read(StrR)
                End If
            End While
            StrR.ReadByte()
            StrR.ReadByte()
            StrR.ReadByte()
            StrR.ReadByte()
        End If

        Return Player
    End Function


#End Region

End Module
